package com.letoken.platform.repo.utlis;

import com.letoken.platform.pub.util.IpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;


@Slf4j
public class UniqueIDUtils {

	static UniqueIDUtils snowFlake = new UniqueIDUtils();

	private long datacenterId; // 数据中心
	private long machineId; // 机器标识
	private AtomicInteger sequence = new AtomicInteger(0); // 序列号
	private long lastStmp = -1L;// 上一次时间戳
	private final static long MAX_SEQUENCE = 10000;


	private UniqueIDUtils() {
		String DATACENTER_ID = System.getenv("DATACENTER_ID");
		String MACHINE_ID = System.getenv("MACHINE_ID");
		long datacenterId = ObjectUtils.isEmpty(DATACENTER_ID) ? 2 : Long.parseLong(DATACENTER_ID);
		String ipAddr = IpUtils.getLocalIPAddr();

		long machineId = ObjectUtils.isEmpty(MACHINE_ID) ? 3 : Long.parseLong(MACHINE_ID);
		log.info("UniqueIDUtils init  datacenterId  {} machineId {} ip {}", datacenterId, machineId, ipAddr);
		this.datacenterId = datacenterId;
		this.machineId = machineId;
	}

	private long getNewstmp() {
		return System.currentTimeMillis();
	}

	/**
	 * @return
	 */
	private synchronized String nextId() {
		long currStmp = getNewstmp();
		if (currStmp < lastStmp) {
			throw new RuntimeException("Clock moved backwards.  Refusing to generate id");
		}
		int seq;
		if (currStmp == lastStmp) {
			// 相同毫秒内，序列号自增
			seq = sequence.getAndIncrement();
			// log.info("+++++++++++++++++++++++++++"+seq);
			// 同一毫秒的序列数已经达到最大
			if (seq > MAX_SEQUENCE) {
				currStmp = getNextMill();
				seq = sequence.getAndSet(0);
			}
		} else {
			// log.info(currStmp +"=========================="+lastStmp);
			// 不同毫秒内，序列号置为0
			sequence.getAndSet(0);
			seq = sequence.getAndIncrement();
		}

		lastStmp = currStmp;
		String date = lastStmp + "" + machineId + datacenterId;
		date = date + String.format("%04d", seq);
		return date;
	}

	private long getNextMill() {
		long mill = getNewstmp();
		while (mill <= lastStmp) {
			mill = getNewstmp();
		}
		return mill;
	}


	/**
	 * 生成userCode
	 *
	 * @return
	 */
	public static String genSeqNo(String type) {
		if (StringUtils.isBlank(type)) type = "SEQ";
		type = type.toUpperCase();
		Random n = new Random();
		Long seed = System.nanoTime();
		n.setSeed(seed);
		return type + String.format("%04d", n.nextInt(10000)) + snowFlake.nextId();
	}


	public static String getSnowFlake() {
		return snowFlake.nextId();
	}

	static char[] BIG = {'A','B','C','D','E','F','G','H','J','K'};
	static char[] LITTLE = {'a','b','c','d','e','f','g','h','j','k'};

	public static String getUid(String prefix,Integer id,Boolean isNumber){
		String sou = String.valueOf(id);
		int i = 10 - sou.length();
		Random random = new Random();
		Long seed = System.nanoTime();
		random.setSeed(seed);
		String v =  String.format("%04d%08d", random.nextInt(10000),id);

		if (isNumber) return v;

		StringBuilder sb = new StringBuilder();
		sb.append(prefix);
		long t = Long.valueOf(v);
		int f = 0;
		while (t > 0){
			f = (int)(t % 10);
			sb .append(BIG[f]);
			t = t / 10;
		}

		return sb.toString();
	}


	public static void main(String[] args) {
		Set<String> a = new HashSet<>();
		for (int i = 0; i < 1000000; i++){
			String t =  getUid("",i,true);
			if (a.contains(t)){
				System.out.println("出现重复编号:" + t);
			}
			if (t.length() != 12){
				System.out.println("长度不对:" + t);
			}
			a.add(t);
			System.out.println(t);
		}

	}





}
